package com.ehome.poct.core.dao.mybatis;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ehome.poct.core.api.dto.check.CheckOnlineRecord;
import com.ehome.poct.core.api.dto.common.DeviceCheckStatusEnum;
import com.ehome.poct.core.api.vo.online.TodoOrderVO;
import com.ehome.poct.core.api.vo.patient.PatientDetailVO;
import com.ehome.poct.core.dao.entity.TermPatientDO;
import com.ehome.poct.core.dao.entity.check.TestUniRecordDO;
import com.ehome.poct.core.dao.mybatis.mapper.PatientMapper;
import com.ehome.poct.core.dao.mybatis.mapper.TestUniRecordMapper;
import com.ehome.poct.core.properties.CheckProperties;
import com.ehome.poct.core.repository.OnlineCheckRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 联机检测
 *
 * @author gyl
 * @since 2022/3/5 14:47
 **/
@Repository
public class OnlineCheckRepositoryImpl implements OnlineCheckRepository {

    @Autowired
    private TestUniRecordMapper recordMapper;
    @Autowired
    private PatientMapper patientMapper;
    @Autowired
    private CheckProperties checkProperties;

    @Override
    public CheckOnlineRecord saveUniRecord(CheckOnlineRecord record) {
        var recordDO = toTestUniRecordDO(record);
        recordDO.insert();
        record.setId(recordDO.getTestUniRecordId());
        record.setCreateTime(recordDO.getCreateTime());
        return record;
    }

    @Override
    public List<TodoOrderVO> getTodoList(Long clinicId) {
        var records = recordMapper.selectList(Wrappers.<TestUniRecordDO>lambdaQuery().eq(TestUniRecordDO::getTermClinicId, clinicId)
                .ne(TestUniRecordDO::getXcgStatus, 10)
                .orderByDesc(TestUniRecordDO::getCreateTime));
        var patientIds = records.parallelStream().map(TestUniRecordDO::getPatientId).collect(Collectors.toList());
        var patientMap = Optional.ofNullable(patientIds).filter(CollectionUtil::isNotEmpty)
                .map(p -> patientMapper.selectList(Wrappers.<TermPatientDO>lambdaQuery().in(TermPatientDO::getTermPatientId, p))
                        .parallelStream().collect(Collectors.toMap(TermPatientDO::getTermPatientId, o -> o))).orElse(new HashMap<>(1));
        return records.stream().map(r -> toTodoOrderVO(r, toPatientDetailVO(patientMap.get(r.getPatientId())))).collect(Collectors.toList());
    }

    @Override
    public int deleteUniRecord(Long recordId) {
        return recordMapper.deleteById(recordId);
    }

    @Override
    public TodoOrderVO findById(Long recordId) {
        var recordDO =  recordMapper.selectOne(Wrappers.<TestUniRecordDO>lambdaQuery().eq(TestUniRecordDO::getTestUniRecordId, recordId));
        return toTodoOrderVO(recordDO, null);
    }

    @Override
    public int updateUniRecordStatus(Long recordId, DeviceCheckStatusEnum status, String orderNo) {
        return recordMapper.update(null, Wrappers.<TestUniRecordDO>lambdaUpdate()
                .eq(TestUniRecordDO::getTestUniRecordId, recordId)
                .set(TestUniRecordDO::getXcgStatus, status.getType())
                .set(TestUniRecordDO::getXcgFinishTime, LocalDateTime.now())
                .set(TestUniRecordDO::getUpdateTime, LocalDateTime.now())
                .set(StrUtil.isNotBlank(orderNo), TestUniRecordDO::getTestOrderNo, orderNo));
    }


    private static TestUniRecordDO toTestUniRecordDO(CheckOnlineRecord record) {
        return new TestUniRecordDO().setTestUniRecordName("CRP+SAA+血常规")
                .setJbyStatus(record.getPoctProcess().getStatus().getType())
                .setXcgStatus(record.getBloodProcess().getStatus().getType())
                .setTestStatus(1).setPatientId(record.getPatientId()).setPatientName(record.getPatientName())
                .setTermClinicId(record.getClinicId()).setWakeUpDevice(record.getInitiateType().getType());
    }

    private TodoOrderVO toTodoOrderVO(TestUniRecordDO record, PatientDetailVO patient) {
        if (null == record && null == patient) {
            return null;
        }
        TodoOrderVO todoOrderVO = new TodoOrderVO();
        if (null != record) {
            todoOrderVO.setRecordId(record.getTestUniRecordId());
            todoOrderVO.setXcgStatus(record.getXcgStatus());
            todoOrderVO.setJbyStatus(record.getJbyStatus());
            todoOrderVO.setXcgFinishTime(record.getXcgFinishTime());
            todoOrderVO.setJbyFinishTime(record.getJbyFinishTime());
            todoOrderVO.setCreateTime(record.getCreateTime());
            todoOrderVO.setExpired(null != checkProperties.getOnlineExpired()
                    && record.getCreateTime().isBefore(LocalDateTime.now().minusHours(checkProperties.getOnlineExpired())));
        }
        if (null != patient) {
            todoOrderVO.setPatient(patient);
        }
        return todoOrderVO;
    }

    public PatientDetailVO toPatientDetailVO(TermPatientDO entity) {
        if (null == entity) {
            return null;
        }
        PatientDetailVO patientDetailVO = new PatientDetailVO();
        patientDetailVO.setPatientId(entity.getTermPatientId());
        patientDetailVO.setClinicId(entity.getTermClinicId());
        patientDetailVO.setUserName(entity.getName());
        patientDetailVO.setMobilePhone(entity.getPhone());
        if (null != entity.getAge()) {
            patientDetailVO.setUserAge(entity.getAge().intValue());
        }
        patientDetailVO.setUserMonth(entity.getMonth());
        patientDetailVO.setUserSex(entity.getSex());
        return patientDetailVO;
    }
}
